package com.yunform.framework.util.js;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.apache.commons.lang.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.yunform.framework.util.serialize.JsonUtil;

public class JavaScriptExecuteEngine {
	
	Logger  logger = LoggerFactory.getLogger(JavaScriptExecuteEngine.class);
	ScriptEngineManager engineManager = new ScriptEngineManager(); 
	
	/**
	 * process完成后，把context对象序列化为JSON返回
	 * @param context
	 * @param script
	 * @return 
	 * @throws ScriptException 
	 */
	public String  executeReturnContext(String action,Map<String,Object> javaObjList,Object context, String script,String contextVarName) throws JavaScriptExecuteException {
		if(script==null) return null;
		
		 ScriptEngine engine = buildScriptEngine(javaObjList);
		 StringBuffer data = new StringBuffer();
		 if(context!=null){
			 data.append("var context="+JsonUtil.serializeToJson(context)+";\n");
		 }
		 String fullScript = data.toString()+script+"\nJSON.stringify("+contextVarName+")";
		 
		 Object retObj;
		try {
			retObj = engine.eval(fullScript);
			return (String)retObj;
			
		} catch (ScriptException e) {
			throw new JavaScriptExecuteException(action,fullScript,e);
		}
		
		
	
	}

	private ScriptEngine buildScriptEngine(Map<String, Object> javaObjList) {
		
		 ScriptEngine engine = engineManager.getEngineByName("JavaScript");
		 if(javaObjList!=null){
			 Iterator<String> iterator = javaObjList.keySet().iterator();
			 while(iterator.hasNext()){
				 String key = iterator.next();
				 Object obj = javaObjList.get(key);
				 engine.put(key, obj);
			 }
		 }
		return engine;
	}
	
	/**
	 * 模板引擎渲染text/html
	 * @param context
	 * @param script
	 * @return
	 * @throws ScriptException 
	 */
	public String  executeReturnText(String action,Map<String,Object> javaObjList,String context, String script) throws JavaScriptExecuteException {
		if(script==null) return null;
		
		 ScriptEngine engine = this.buildScriptEngine(javaObjList);
		 
		 StringBuffer data = new StringBuffer();
		 if(context!=null){
			 data.append("var context="+context+";\n");
		 }
		 String fullScript = data.toString()+script ;
		 Object retObj;
		try {
			retObj = engine.eval(fullScript);
			return (String)retObj;
		} catch (ScriptException e) {
			throw new JavaScriptExecuteException(action,fullScript,e);
		}
		
	
	}
	
	/**
	 * 获取engine中的yo
	 * @param name
	 * @return
	 */
//	public Object getVar(String name){
//		try {
//			return engine.eval(name);
//		} catch (ScriptException e) {
//			logger.error(e.getMessage(),e);
//			return null;
//		}
//	}
	
	public static String compile(String script){
		StringBuffer sb = new StringBuffer();
		sb.append("var _out=\"\";\n");
		String regex = "<%={0,1}|%>";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(script);
		String pre = null;
		while(matcher.find()){
			String find = matcher.group(0);
//			sb.append("--"+find+"---");
			StringBuffer item = new StringBuffer();
			matcher.appendReplacement(item, "");
			if(find.endsWith("<%") || find.equals("<%=")){
				String jsString = "_out=_out.concat(\""+StringEscapeUtils.escapeJavaScript(item.toString())+"\");\n";
				sb.append(jsString);
			}else if (find.equals("%>")){
				if(pre.equals("<%")){
					sb.append("\n"+item.toString());
				}else if (pre.equals("<%=")){
					String jsString = "_out=_out.concat("+item.toString()+");\n";
					sb.append(jsString);
				}
			}
			
			pre = find;
		}
		StringBuffer item = new StringBuffer();
		matcher.appendTail(item);
		String jsString = "_out=_out.concat(\""+StringEscapeUtils.escapeJavaScript(item.toString())+"\");\n";
		sb.append(jsString);
		return sb.toString();
	}
	
	public static void main(String[] args) throws JavaScriptExecuteException{
		
		
		String text = 
"aaa\"123..\n"+
"<%if(list.length>1) { %>\n"+
"        <h2>输出list，共有<%=list.length%>个元素</h2>\n"+
"        <ul>\n"+
"            <!-- 循环语句 for-->\n"+
"            <%for(var i=0;i<5;i++){%>\n"+
"                <li><%=list[i]%></li>\n"+
"            <%}%>\n"+
 "       </ul>\n"+
 "   <%}else{%>\n"+
 "       <h2>没有list数据</h2>   \n"+
"    <%}%>\n";

		String compileText = JavaScriptExecuteEngine.compile(text);
		System.out.println(compileText);
		Map<String,Object> data = new HashMap<String,Object>();
		data.put("list", new String[]{"aa","bb","cc"});
		String html = new JavaScriptExecuteEngine().executeReturnText("test",null,JsonUtil.serializeToJson(data), compileText);
		System.out.println(html);
	}
	
}
